c语言 您所在的位置:网站首页 C语言必备知识 2数组以及static详解 c语言

c语言

2024-06-24 02:54| 来源: 网络整理| 查看: 265

文章目录 一、一维数组1.一维数组的创建和初始化(1).数组的创建(2).数组的初始化 2.一维数组的使用3.一维数组在内存中的存储 二、二维数组1.二维数组的创建和初始化(1).二维数组的创建(2).二维数组的初始化 2.二维数组的使用3.二维数组在内存中的存储 三、数组作为函数参数1.一维数组2.二维数组 四、数组指针和指针数组1.指针数组2.数组指针

一、一维数组 1.一维数组的创建和初始化 (1).数组的创建

数组是一组相同类型元素的集合。 数组的创建方式:

type_t arr_name [const_n]; //type_t 是指数组的元素类型 //arr_name 是数组的名字 //const_n 是一个常量表达式,用来指定数组的大小

数组创建的实例:

//代码1 int arr1[10]; char arr2[10]; float arr3[1]; double arr4[20]; //代码2 //用宏定义的方式 #define X 3 int arr5[X]; //代码3 //错误使用 int count = 10; int arr6[count];//数组时候可以正常创建?

注:数组创建, [] 中要给一个常量才可以,不能使用变量。可以直接用常量,或者使用宏定义。

(2).数组的初始化

数组的初始化是指,在创建数组的同时给数组的内容一些合理初始值(初始化)。 看代码:

数组大小和数值个数一致 int arr1[5] = {1,2,3,4,5};

初始化后各元素的值 在这里插入图片描述

数组大小大于初始数 int arr2[6] = {1,2,3};

初始化后各元素的值 在这里插入图片描述

不指定数组大小 int arr3[] = {1,2,3,4};

初始化后各元素的值 在这里插入图片描述

不指定字符数组大小 char arr5[] = {'a','b','c'};

初始化后各元素的值 在这里插入图片描述

注意数组大小和最后一项的差别 (1)字符数组存储字符串 char arr6[] = "abcdef";

初始化后各元素的值 在这里插入图片描述

(2)字符数组的大小和字符串字符个数一致时

char arr6[6] = "abcdef";

在这里插入图片描述

!!这样初始化是有问题的,因为无法正常读取字符串的结束标志('\0'),导致字符串的长度和内容不能得知!!

字符数组大小大于字符串中的字符数 char arr7[6] = "zxc";

初始化后各元素的值 在这里插入图片描述

结论

数组是具有相同类型的集合,数组的大小(即所占字节数)由元素个数乘以单个元素的大小。数组只能够整体初始化,不能被整体赋值。只能使用循环从第一个逐个遍历赋值。初始化时,数组的维度或元素个数可忽略 ,编译器会根据花括号中元素个数初始化数组元素的个数。当花括号中用于初始化值的个数不足数组元素大小时,数组剩下的元素依次用0初始化。字符型数组在计算机内部用的时对应的ascii码值进行存储的。一般用”“引起的字符串,不用数组保存时,一般都被直接编译到字符常量区,并且不可被修改。

在内存中的存储

2.一维数组的使用

[ ] ,下标引用操作符。它其实就数组访问的操作符。 我们来看代码:

#include int main() { int arr[10] = { 0 };//数组的不完全初始化 //计算数组的元素个数 int sz = sizeof(arr) / sizeof(arr[0]); //对数组内容赋值,数组是使用下标来访问的,下标从0开始。所以: int i = 0;//做下标,此时可以是变量 for (i = 0; i printf("%d ", arr[i]); } return 0; }

注意:

sizeof()操作符用于取长度,以字节为单位。sizeof(数组名)即求的时整个数组的大小。sizeof(首元素)即求数组单个元素大小。用0下标,是因为数组至少存在一个有效元素,所以0下标永远存在。数组是使用下标来访问的,下标是从0开始。数组的大小可以通过计算得到。建议采用sizeof(arr)/sizeof(arr[0])这种方式。 3.一维数组在内存中的存储

先看代码吧:

#include int main() { int arr[10] = { 0 }; int size = sizeof(arr) / sizeof(arr[0]); for (int i = 0; i 1,2,3,4}; int arr[3][4] = {{1,2},{4,5}}; int arr[][4] = {{2,3},{4,5}};

注意: 花括号中的一个花括号代表一个一维数组的初始化。当里面无花括号分组时,按照顺序从第一个开始逐个进行初始化。余下的未赋值的元素用0初始化。

2.二维数组的使用

二维数组的使用也是通过下标的方式,用双重循环嵌套进行索引使用。 看代码:

#include int main() { int arr[3][4] = { 0 }; int i = 0; for (i = 0; i arr[i][j] = i * 4 + j; } } for (i = 0; i printf("%d ", arr[i][j]); } } return 0; } 3.二维数组在内存中的存储

像一维数组一样,这里我们尝试打印二维数组的每个元素。

#include int main() { int arr[3][4]; int i = 0; for (i = 0; i printf("&arr[%d][%d] = %p\n", i, j, &arr[i][j]); } } return 0; }

输出结果为: 在这里插入图片描述

通过结果我们可以分析到,其实二维数组在内存中也是连续存储的。

注意:

二维数组在内存的空间布局上,也是线性连续且递增的!!!二维数组本质上也是一维数组,只不过内部元素放的是一维数组。 三、数组作为函数参数 调用函数传参数组时,减少函数传数组时的成本问题(时间和空间)。因为传参时,需要临时拷贝,如果数组过大,可能会浪费资源,严重的话可能栈溢出。数组元素降维成指向数组内部元素类型的指针。对指针加一,加上所指向的类型的大小。 1.一维数组 #include void Lisa(int arr[]) { printf("a = %d\n", sizeof(arr));//数组降维成指针后的指针大小,在32位系统下指针都为4字节 printf("b = %d\n", sizeof(arr[0]));//数组首元素的大小 printf("sz =a / b = %d\n", sizeof(arr) / sizeof(arr[0]));//大小为1 printf("arr = %p\n", arr);//数组首元素地址 printf("&arr = %p\n", &arr);//指针的地址 printf("arr + 1 = %p\n", arr + 1);//下一个元素的地址 printf("&arr + 1 = %p\n", &arr + 1);//指针下一项的地址 } int main(void) { int Shuzu[10] = { 0,1,2,3,4,5,6,7,8,9 }; printf("a = %d\n", sizeof(Shuzu));//数组总大小 printf("b = %d\n", sizeof(Shuzu[0]));//数组首元素大小 printf("sz =a / b = %d\n", sizeof(Shuzu) / sizeof(Shuzu[0]));//数组元素个数 printf("Shuzu = %p\n", Shuzu);//数组首元素地址 printf("&Shuzu = %p\n", &Shuzu);//代表整个数组,但是地址仍是首元素地址 printf("Shuzu + 1 = %p\n", Shuzu + 1);//下一个元素的地址 printf("&Shuzu + 1 = %p\n", &Shuzu + 1);//跳过整个数组后紧挨着的地址 //此时该地址减去首元素地址等于数组大小 printf("\n\n"); Lisa(Shuzu); return 0; }

补充

sizeof(数组名),计算整个数组的大小,sizeof内部单独放一个数组名,数组名表示整个数组。&数组名,取出的是数组的地址。&数组名,数组名表示整个数组。

!!画图解析!! 在这里插入图片描述

总结:

形参格式,例如int arr[ ]或者int *arr,两者等价形参元素个数可被忽略,并且建议忽略(有可能改变了实参的大小,这样比较方便)。或者也可以填写比实参元素个数大的值。用sizeof()求数组元素个数时,尽量在数组定义时求。因为传参后数组会降维成指针。 2.二维数组

前面说了数组元素降维成指向数组内部元素类型的指针,二维int整型数组的内部元素不再是int整型,而是具有四个整型的一维数组。 对指针加一,加上所指向的类型的大小。对二维数组的指针加一,加上的值为内部一维数组的大小。 看代码:

#include void Lisa(int arr[][4]) { printf("a = %d\n", sizeof(arr));//数组降维成指针后的指针大小,在32位系统下指针都为4字节 printf("b = %d\n", sizeof(arr[0][0]));//数组首元素的大小 printf("sz =a / b = %d\n", sizeof(arr) / sizeof(arr[0][0]));//大小为1 printf("arr = %p\n", arr);//数组首元素地址 printf("arr + 1 = %p\n", arr + 1);//下一个元素的地址 printf("&arr = %p\n", &arr);//指针的地址 printf("&arr + 1 = %p\n", &arr + 1);//指针下一项的地址 } int main(void) { int Shuzu[3][4] = { 0,1,2,3,4,5,6,7,8,9 }; printf("a = %d\n", sizeof(Shuzu));//数组总大小 printf("b = %d\n", sizeof(Shuzu[0][0]));//数组首元素大小 printf("sz =a / b = %d\n", sizeof(Shuzu) / sizeof(Shuzu[0][0]));//数组元素个数 printf("Shuzu = %p\n", Shuzu);//数组首元素地址 printf("Shuzu + 1 = %p\n", Shuzu + 1);//下一个元素的地址,这时其内部元素的一维数组 printf("&Shuzu = %p\n", &Shuzu);//代表整个数组,但是地址仍是首元素地址 printf("&Shuzu + 1 = %p\n", &Shuzu + 1);//跳过整个数组后紧挨着的地址 //此时该地址减去首元素地址等于数组大小 printf("\n\n"); Lisa(Shuzu); return 0; }

画图解释 在这里插入图片描述

形参格式,例如:int arr[][4]或者int (*arr)[4],这里为指向具有四个整型元素的一维数组的数组指针。除了第一个中括号里的数字可以省,后面的中括号的内容不能省略,因为下标是数组类型的一部分,省略掉就不明确其类型。 注意: 看待所有的数组时,都将它看作一维数组,只不过其内部元素不一样,例如:三维数组其内部元素为二维数组,而二维数组也是有一维数组组成,都是线性连续且相等的。

四、数组指针和指针数组 数组指针:是指针,指向数组。例:int (*arr)[10]指针数组:是数组,数组内容存放的是指针。例:int *arr[10]

然后,需要明确一个优先级顺序:()>[]>* 所以: (*p)[n]:根据优先级,先看括号内,则p是一个指针,这个指针指向一个一维数组,数组长度为n,这是“数组的指针”,即数组指针; *p[n]:根据优先级,先看[],则p是一个数组,再结合*,这个数组的元素是指针类型,共n个元素,这是“指针的数组”,即指针数组。

1.指针数组

具体使用:

#include int main(void) { int *p[4]; int arr1[3] = { 1,2,3 }; int arr2[4] = { 2,4,6,8 }; int arr3[5] = { 0 }; int arr4[2] = { 2,2 }; p[0] = arr1; p[1] = arr2; p[2] = arr3; p[3] = arr4; printf("%d\n", *(p[0] + 1)); printf("%d\n", *(p[1] + 1)); printf("%d\n", *(p[2] + 1)); printf("%d\n", *(p[3] + 1)); return 0; }

输出结果: 在这里插入图片描述

首先,对于语句int*p[4],因为[ ]的优先级要比*要高,所以 p 先与[ ]结合,构成一个数组的定义,数组名为 p,而int*修饰的是数组的内容,即数组的每个元素。也就是说,该数组包含 4 个指向int类型数据的指针,如图所示,因此,它是一个指针数组。

2.数组指针

使用:

#include int main(void) { int Shuzu[3][4] = { 0,1,2,3,4,5,6,7,8,9,0,0 }; int(*arr)[4] = Shuzu; for (int i = 0;i printf("arr[%d][%d]=%d ", i,j,arr[i][j] ); } printf("\n"); } return 0; }

结果为: 在这里插入图片描述

其次,对于语句int(*arr)[4],“( )”的优先级比[ ]高,*号和 arr 构成一个指针的定义,指针变量名为 arr,而 int 修饰的是数组的内容,即数组的每个元素。也就是说,arr 是一个指针,它指向一个包含 4 个int类型数据的数组,如图 所示。很显然,它是一个数组指针。

还有很多的瑕疵,欢迎提出并改正



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有